using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Framework.Serialization;
using IQIGame.Onigao.Logic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay.Editors
{
    public class SerializeCustomConfigBatch
    {
        private static Encoding UTF8 = new UTF8Encoding(false);

        private class BatchItem
        {
            public string batchPath;
            public Type baseType;
            public SerializableGroup attributeGroup;
        }

        private struct DictKeyValueType : IEquatable<DictKeyValueType>
        {
            public Type key;
            public Type value;

            public DictKeyValueType(Type key, Type value)
            {
                this.key = key;
                this.value = value;
            }

            public bool Equals(DictKeyValueType other)
            {
                return this.key == other.key && this.value == other.value;
            }
        }

        private const string scriptsPath = "Assets/Scripts/GamePlay/Runtime/Module/Share/Battle/Config/";

        private static List<BatchItem> s_BatchList = new List<BatchItem>()
            {
                new BatchItem() //通过基类收集
                {
                    batchPath = scriptsPath,
                    baseType = typeof(SkillCustomConfig)
                },
                new BatchItem() //通过基类收集
                {
                    batchPath = scriptsPath,
                    baseType = typeof(SkillEffectiveAction_ParamBase)
                },
                new BatchItem() //通过基类收集
                {
                    batchPath = "Assets/Scripts/GamePlay/Editor/LevelEditor/LevelService/ServiceConfig/Batch/",
                    baseType = typeof(LevelServiceCustomConfig)
                },
                new BatchItem() //通过Attribute收集
                {
                    batchPath = "Assets/Scripts/GamePlay/Runtime/Module/Share/Level/Config/Serialization/",
                    attributeGroup = SerializableGroup.LevelModuleConfig
                },
                new BatchItem() //通过Attribute收集
                {
                    batchPath = "Assets/Scripts/GamePlay/Runtime/Module/GamePlayArea/MainCity/Config/Serialization/",
                    attributeGroup = SerializableGroup.MainCityModuleConfig
                },
                new BatchItem() //通过Attribute收集
                {
                    batchPath = "Assets/Scripts/GamePlay/Runtime/Logic/Story/Config/Batch/",
                    attributeGroup = SerializableGroup.StoryModuleConfig
                },
                new BatchItem() //通过Attribute收集
                {
                    batchPath = "Assets/Scripts/GamePlay/Runtime/Module/Share/BehavScript/Serialization/",
                    attributeGroup = SerializableGroup.BehavScript
                },
                new BatchItem() //通过Attribute收集
                {
                    batchPath = "Assets/Scripts/GamePlay/Runtime/Module/Story/ActionConfig/Batch/",
                    attributeGroup = SerializableGroup.StoryActionConfig
                },
            };

        private static List<Type> s_toSerializeFixedType = new List<Type>()
        {
            typeof(Framework.Vector3Int),
            typeof(Vector3),
            typeof(Game.RectInt),
            typeof(DynCfgKey),
            typeof(ItemCidNumPair),
            typeof(DialogReference),
            typeof(Vector2),
        };

        /// <summary>
        /// 抽象类对应的子类
        /// key：抽象类，key：子类，value：枚举值
        /// </summary>
        private static Dictionary<Type, Dictionary<Type, int>> s_SubClassEnumDict = new();
        /// <summary>
        /// 抽象类对应的枚举类名
        /// </summary>
        private static Dictionary<Type, string> s_SubClassEnumDict2 = new();

        [MenuItem("GameEditor/SerializeCustomConfig/生成配置序列化文件", false, 1)]
        public static void BatchScripts()
        {
            //生成所有fixed类型(底层代码，无法或不方便改动)的扩展方法
            GenFixedType();
            //所有的Dictionary类型字段，后面特殊生成序列化/反序列化代码
            HashSet<DictKeyValueType> dicts = new();
            //for GenerateSubClassEnums()
            s_SubClassEnumDict.Clear();
            s_SubClassEnumDict2.Clear();
            //生成配置在s_BatchList里的GamePlay里的业务类的序列化/反序列化代码
            for (int x = 0; x < s_BatchList.Count; x++)
            {
                //遍历所有配置
                var rBatch = s_BatchList[x];
                Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
                var rList = new List<Type>();
                //是否以基类为准生成所有子类的序列化/反序列化代码
                var configBaseType = rBatch.baseType;
                //是否以指定groupName的Attribute为准生成序列化/反序列化代码
                var configAttrGroup = rBatch.attributeGroup;
                foreach (Assembly assembly in assemblies)
                {
                    Type[] types = assembly.GetTypes();

                    foreach (Type type in types)
                    {
                        if (configBaseType != null) //通过基类收集
                        {
                            if (type.IsSubclassOf(configBaseType))
                            {
                                rList.Add(type);
                            }
                        }
                        else if (configAttrGroup != SerializableGroup.None) //通过Attribute收集
                        {
                            var attr = type.GetCustomAttribute<SerializableGroupAttribute>();
                            if (attr != null && attr.group == configAttrGroup)
                            {
                                rList.Add(type);
                            }
                        }
                    }
                }

                //先生成抽象基类对应的所有子类的枚举键值对，以便于序列化
                GenerateSubClassEnums(rList);

                //遍历根据配置的基类或Attribute收集到的所有类
                for (int i = 0; i < rList.Count; i++)
                {
                    var rType = rList[i];
                    var rFields = rType.GetFields(BindingFlags.Instance | BindingFlags.Public);
                    CollectDictionary(rFields, dicts);

                    //当前类是否需要自己定制化部分序列化和反序列化
                    bool curTypeNeedCustom = typeof(SerializeCustomConfig).IsAssignableFrom(rType);
                    //当前类的Serialize和DeSerialize接口是否重写基类（如果不是，则为直接实现接口）
                    bool isOverride = configBaseType != null || curTypeNeedCustom;

                    var rSb = new StringBuilder();
                    rSb.AppendUnixLine("using System.Collections.Generic;");
                    rSb.AppendUnixLine("using IQIGame.Onigao.Framework.Serialization;");
                    rSb.AppendUnixLine("using IQIGame.Onigao.GamePlay;");
                    rSb.AppendUnixLine("using IQIGame.Onigao.Logic;");
                    rSb.AppendUnixLine($"namespace {rType.Namespace}");
                    rSb.AppendUnixLine("{");
                    rSb.AppendUnixLine("    /// <summary>");
                    rSb.AppendUnixLine("    /// auto generated code");
                    rSb.AppendUnixLine("    /// 自动生成的代码");
                    rSb.AppendUnixLine("    /// </summary>");
                    rSb.AppendUnixLine($"    public partial {(rType.IsValueType ? "struct" : "class")} {rType.Name}{(isOverride ? string.Empty : " : ISerializeByteBuf")}");
                    rSb.AppendUnixLine("    {");
                    rSb.AppendUnixLine($"        public {(isOverride ? "override " : string.Empty)}void Serialize(ByteBuf _buf)");
                    rSb.AppendUnixLine("        {");
                    if (isOverride)
                    {
                        rSb.AppendUnixLine("            base.Serialize(_buf);");
                    }

                    for (int j = 0; j < rFields.Length; j++)
                    {
                        var rField = rFields[j];
                        string fieldCode = ConcatFieldCode(rField.FieldType, rField.Name, j, "this.", true);
                        if (fieldCode != null)
                        {
                            rSb.AppendUnixLine("            " + fieldCode);
                        }
                        else
                        {
                            Debug.LogError($"{rType} 生成序列化文件内容失败，包含未定义的类型，需要补充. [{rField} 类型：{rField.FieldType.FullName}");
                        }
                    }

                    if (curTypeNeedCustom)
                    {
                        rSb.AppendUnixLine("            this.OnSerialize(_buf);");
                    }

                    rSb.AppendUnixLine("        }");
                    rSb.AppendUnixLine();
                    rSb.AppendUnixLine($"        public {(isOverride ? "override " : string.Empty)}void DeSerialize(ByteBuf _buf)");
                    rSb.AppendUnixLine("        {");
                    if (isOverride)
                    {
                        rSb.AppendUnixLine("            base.DeSerialize(_buf);");
                    }
                    for (int j = 0; j < rFields.Length; j++)
                    {
                        var rField = rFields[j];
                        rSb.AppendUnixLine("            " + ConcatFieldCode(rField.FieldType, rField.Name, j, "this.", false));
                    }

                    if (curTypeNeedCustom)
                    {
                        rSb.AppendUnixLine("            this.OnDeSerialize(_buf);");
                    }

                    rSb.AppendUnixLine("        }");
                    rSb.AppendUnixLine("    }");
                    rSb.AppendUnixLine("}");

                    var rFilePath = rBatch.batchPath + rType.Name + ".cs";
                    SaveCode(rFilePath, rSb.ToString());
                }
            }

            //生成字典序列化/反序列化工具API
            GenDictinaryUtilAPI(dicts);

            LogGame.Log("序列化生成完成");
            AssetDatabase.Refresh();
        }

        /// <summary>
        /// 收集所以字段类型为抽象类的子类枚举值到静态缓存里
        /// </summary>
        /// <param name="rList"></param>
        private static void GenerateSubClassEnums(List<Type> rList)
        {
            //获取所有需要序列化的字段里，类型是抽象类的
            HashSet<Type> abstractClasses = new HashSet<Type>();
            foreach (Type rType in rList)
            {
                FieldInfo[] rFields = rType.GetFields();
                foreach (FieldInfo rField in rFields)
                {
                    bool isList = IsList(rField.FieldType);
                    bool isDectionary = IsDictionary(rField.FieldType);
                    if (rField.FieldType.IsAbstract && !(isList || isDectionary)) //抽象类(排除抽象类型的集合)
                    {
                        abstractClasses.Add(rField.FieldType);
                    }
                    else if (rField.FieldType.IsGenericType) //抽象类泛型
                    {
                        foreach (Type genericType in rField.FieldType.GenericTypeArguments)
                        {
                            if (genericType.IsAbstract)
                            {
                                abstractClasses.Add(genericType);
                            }
                        }
                    }
                    else if (rField.FieldType.IsArray) //抽象类数组
                    {
                        Type elementType = rField.FieldType.GetElementType();
                        if (elementType.IsAbstract)
                        {
                            abstractClasses.Add(elementType);
                        }
                    }
                }
            }
            foreach (Type abstractType in abstractClasses)
            {
                //枚举类名规则是抽象类包名最后一个.后面的string+抽象类名
                //兼顾尽量不重复和文件名不过长
                List<Type> subTypes = abstractType.GetSubTypes();
                if (subTypes.Count == 0)
                {
                    continue;
                }
                //只要有子类没有实现ISerializeByteBuf，且没有SerializableGroupAttribute，不支持
                if (!subTypes[0].GetInterfaces().Contains(typeof(ISerializeByteBuf))
                    && subTypes[0].GetCustomAttribute<SerializableGroupAttribute>() == null)
                {
                    continue;
                }
                string[] parts = abstractType.GetFullNameWithoutDLL().Split(".");
                string enumClassName;
                //枚举和枚举类型映射的className：是GamePlay的自定义类就直接用抽象类名+固定后缀，否则为了保险起见，前面再加上NameSpace最后一位单词
                //最好不要统一用加上NameSpace后缀的命名方式，否则可能出现大量无效的GamePlay_前缀。
                if (abstractType.Namespace == "IQIGame.Onigao.GamePlay")
                {
                    enumClassName = parts[parts.Length - 1];
                }
                else
                {
                    enumClassName = parts[parts.Length - 2] + "_" + parts[parts.Length - 1];
                }
                //去掉内部类的+
                enumClassName = enumClassName.Replace('+', '_') + "Sub";
                string fileRoot = Application.dataPath + "/Scripts/GamePlay/Runtime/Module/Share/Serialization/SubClassEnum/";
                string filePath = fileRoot + enumClassName + ".cs";
                //解析现有enum file，确保老枚举保持不变
                var enumValues = SerializeEnumParser.Parse(filePath, out var maxValue) ?? new();
                Dictionary<Type, int> enumTypeVales = new();
                foreach (Type subType in subTypes)
                {
                    if (!subType.GetInterfaces().Contains(typeof(ISerializeByteBuf)))
                    {
                        continue; //不符合可序列化标准
                    }
                    //已存在直接纪录
                    if (enumValues.TryGetValue(subType.Name, out int value))
                    {
                        enumTypeVales.Add(subType, value);
                    }
                    //不存在的新增，value++
                    else
                    {
                        enumTypeVales.Add(subType, ++maxValue);
                    }
                }
                s_SubClassEnumDict.Add(abstractType, enumTypeVales);
                s_SubClassEnumDict2.Add(abstractType, enumClassName);

                StringBuilder enumValueSB = new StringBuilder();
                StringBuilder getEnumCaseSB = new StringBuilder();
                StringBuilder createSubCaseSB = new StringBuilder();
                foreach (var kv in enumTypeVales)
                {
                    enumValueSB.AppendUnixLine($"        {kv.Key.Name} = {kv.Value},");
                    getEnumCaseSB.Append($@"                case ""{kv.Key.Name}"":
                    e = {enumClassName}.{kv.Key.Name};
                    break;
");
                    createSubCaseSB.Append($@"                case {enumClassName}.{kv.Key.Name}:
                    return new {kv.Key.Name}();
");
                }
                string enumCode = $@"namespace IQIGame.Onigao.GamePlay
{{
    /// <summary>
    /// auto generated code
    /// 自动生成的代码
    /// </summary>
    public enum {enumClassName}
    {{
        None = 0,
{enumValueSB}
    }}
}}
";
                string enumCodePath = $"{Application.dataPath}/Scripts/GamePlay/Runtime/Module/Share/Serialization/SubClassEnum/{enumClassName}.cs";
                SaveCode(enumCodePath, enumCode);

                string subClassMapCode = $@"using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Framework.Serialization;

namespace IQIGame.Onigao.GamePlay
{{
    /// <summary>
    /// auto generated code
    /// 自动生成的代码
    /// </summary>
    public static class {enumClassName}Map
    {{
        public static int GetEnumValue(object field)
        {{
            if (field == null)
            {{
                return 0;
            }}
            {enumClassName} e = default;
            switch (field.GetType().Name)
            {{
{getEnumCaseSB}
                default:
                    LogGame.LogError($""不支持的类型：{{field.GetType().Name}}"");
                    break;
            }}
            return (int)e;
        }}

        public static ISerializeByteBuf CreateObj(int subClassValue)
        {{
            if (subClassValue == 0)
            {{
                return null;
            }}
            {enumClassName} e = ({enumClassName})subClassValue;
            switch (e)
            {{
{createSubCaseSB}
                default:
                    LogGame.LogError($""不支持的Type Enum：{{subClassValue}}"");
                    break;
            }}
            return null;
        }}
    }}
}}
";
                string subClassMapCodePath = $"{Application.dataPath}/Scripts/GamePlay/Runtime/Module/Share/Serialization/SubClassMap/{enumClassName}Map.cs";
                SaveCode(subClassMapCodePath, subClassMapCode);
            }
        }

        /// <summary>
        /// 生成底层固定代码，不好修改为实现ISerializeByteBuf的
        /// </summary>
        private static void GenFixedType()
        {
            foreach (Type type in s_toSerializeFixedType)
            {
                string fileExt = type.GetFullyQualifiedNameForFile(2);

                //获取序列化和反序列化代码段
                StringBuilder sFieldCodes = new StringBuilder();
                StringBuilder desFieldCodes = new StringBuilder();
                var fieldInfos = type.GetFields(BindingFlags.Instance | BindingFlags.Public);
                for (int i = 0; i < fieldInfos.Length; i++)
                {
                    FieldInfo fieldInfo = fieldInfos[i];
                    string sFieldCode = ConcatFieldCode(fieldInfo.FieldType, "v." + fieldInfo.Name, i, null, true);
                    if (sFieldCode == null)
                    {
                        Debug.LogError($"Class类型{type}包含不支持自动序列化的字段{fieldInfo.FieldType}。");
                        continue;
                    }
                    sFieldCodes.AppendUnixLine("            " + sFieldCode);
                    string desFieldCode = ConcatFieldCode(fieldInfo.FieldType, "v." + fieldInfo.Name, i, null, false);
                    desFieldCodes.AppendUnixLine("            " + desFieldCode);
                }

                string code = $@"using IQIGame.Onigao.Framework.Serialization;
using System.Collections.Generic;

namespace IQIGame.Onigao.GamePlay
{{
    /// <summary>
    /// auto generated code
    /// 自动生成的代码
    /// </summary>
    public static class {fileExt}_Extend
    {{
        public static void Serialize(this {type.GetFullyQualifiedName()} v, ByteBuf _buf)
        {{
            {(type.IsValueType ? string.Empty : "_buf.WriteBool(v != null); if (v == null) return;")}
{sFieldCodes}
        }}

        public static {type.GetFullyQualifiedName()} Deserialize(this {type.GetFullyQualifiedName()} _, ByteBuf _buf)
        {{
            {(type.IsValueType ? string.Empty : "if (!_buf.ReadBool()) return null;")}
            {type.GetFullyQualifiedName()} v = {(type.IsValueType ? "default" : "new()")};
{desFieldCodes}
            return v;
        }}

        public static void SerializeList(this IReadOnlyList<{type.GetFullyQualifiedName()}> list, ByteBuf buf)
        {{
            int count = list == null ? 0 : list.Count;
            buf.WriteInt(count);
            for (int i = 0; i < count; i++)
            {{
                list[i].Serialize(buf);
            }}
        }}

        public static List<{type.GetFullyQualifiedName()}> DeserializeList(this IReadOnlyList<{type.GetFullyQualifiedName()}> _, ByteBuf buf)
        {{
            int count = buf.ReadInt();
            List<{type.GetFullyQualifiedName()}> list = new(count);
            for (int i = 0; i < count; i++)
            {{
                {type.GetFullyQualifiedName()} v = default;
                list.Add(v.Deserialize(buf));
            }}
            return list;
        }}

        public static {type.GetFullyQualifiedName()}[] DeserializeArray(this {type.GetFullyQualifiedName()}[] _, ByteBuf buf)
        {{
            int count = buf.ReadInt();
            {type.GetFullyQualifiedName()}[] array = new {type.GetFullyQualifiedName()}[count];
            for (int i = 0; i < count; i++)
            {{
                {type.GetFullyQualifiedName()} v = default;
                array[i] = v.Deserialize(buf);
            }}
            return array;
        }}
    }}
}}
";

                string codePath = Application.dataPath + $"/Scripts/GamePlay/Runtime/Module/Share/Serialization/FixedExtend/{fileExt}_Extend.cs";
                SaveCode(codePath, code);
            }
        }

        /// <summary>
        /// 收集配置的类里所有Dictionary类型的字段（不重复）
        /// </summary>
        /// <param name="rFields"></param>
        /// <param name="dicts"></param>
        private static void CollectDictionary(FieldInfo[] rFields, HashSet<DictKeyValueType> dicts)
        {
            foreach (var fieldInfo in rFields)
            {
                if (IsDictionary(fieldInfo.FieldType))
                {
                    var kvs = fieldInfo.FieldType.GetGenericArguments();
                    Type keyType = kvs[0];
                    Type valueType = kvs[1];
                    dicts.Add(new DictKeyValueType(keyType, valueType));
                }
            }
        }

        /// <summary>
        /// 生成Dictionary的序列化代码
        /// </summary>
        /// <param name="dicts"></param>
        private static void GenDictinaryUtilAPI(HashSet<DictKeyValueType> dicts)
        {
            StringBuilder funcPairs = new StringBuilder();
            foreach (var kv in dicts)
            {
                Type keyType = kv.key;
                Type valueType = kv.value;

                string funcPair = $@"        public static void SerializeDict{keyType.Name}{valueType.Name}(ByteBuf _buf, IReadOnlyDictionary<{keyType.GetFullyQualifiedName()}, {valueType.GetFullyQualifiedName()}> dict)
        {{
            int count = dict?.Count ?? 0;
            _buf.WriteInt(count);
            if (count == 0)
                return;
            foreach (var kv in dict)
            {{
                {ConcatFieldCode(keyType, "kv.Key", 1, "var ", true)}
                {ConcatFieldCode(valueType, "kv.Value", 2, "var ", true)}
            }}
        }}

        public static Dictionary<{keyType.GetFullyQualifiedName()}, {valueType.GetFullyQualifiedName()}> DeserializeDict{keyType.Name}{valueType.Name}(ByteBuf _buf)
        {{
            int count = _buf.ReadInt();
            var dict = new Dictionary<{keyType.GetFullyQualifiedName()}, {valueType.GetFullyQualifiedName()}>();
            for (int i = 0; i < count; i++)
            {{
                {ConcatFieldCode(keyType, "key", 1, "var ", false)}
                {ConcatFieldCode(valueType, "value", 2, "var ", false)}
                dict.Add(key, value);
            }}
            return dict;
        }}
";
                funcPairs.Append(funcPair);
            }

            string code = $@"using System;
using System.Collections.Generic;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Framework.Serialization;
using IQIGame.Onigao.Game;
using IQIGame.Onigao.GamePlay;

namespace IQIGame.Onigao.GamePlay
{{
    /// <summary>
    /// auto generated code
    /// 自动生成的代码
    /// </summary>
    public static class SerializeByteBufUtilExt
    {{
{funcPairs}
    }}
}}
";

            string codePath = Application.dataPath + "/Scripts/GamePlay/Runtime/Module/Share/Serialization/SerializeByteBufUtilExt.cs";
            SaveCode(codePath, code);
        }

        /// <summary>
        /// 拼接每一个字段的序列化/反序列化代码
        /// </summary>
        /// <param name="rFieldType"></param>
        /// <param name="fieldName"></param>
        /// <param name="declaration">反序列化时代码的声明（成员变量可传"this."或string.Empty）</param>
        /// <param name="bSerialize"></param>
        /// <returns></returns>
        private static string ConcatFieldCode(Type rFieldType, string fieldName, int fieldIndex, string declaration, bool bSerialize)
        {
            declaration ??= string.Empty;
            if (rFieldType == typeof(int))
            {
                if (bSerialize)
                {
                    return $"_buf.WriteInt({fieldName});";
                }
                else
                {
                    return $"{declaration}{fieldName} = _buf.ReadInt();";
                }
            }
            else if (rFieldType == typeof(long))
            {
                if (bSerialize)
                {
                    return $"_buf.WriteLong({fieldName});";
                }
                else
                {
                    return $"{declaration}{fieldName} = _buf.ReadLong();";
                }
            }
            else if (rFieldType == typeof(byte))
            {
                if (bSerialize)
                {
                    return $"_buf.WriteByte({fieldName});";
                }
                else
                {
                    return $"{declaration}{fieldName} = _buf.ReadByte();";
                }
            }
            else if (rFieldType == typeof(string))
            {
                if (bSerialize)
                {
                    return $"_buf.WriteString({fieldName});";
                }
                else
                {
                    return $"{declaration}{fieldName} = _buf.ReadString();";
                }
            }
            else if (rFieldType == typeof(bool))
            {
                if (bSerialize)
                {
                    return $"_buf.WriteBool({fieldName});";
                }
                else
                {
                    return $"{declaration}{fieldName} = _buf.ReadBool();";
                }
            }
            else if (rFieldType == typeof(float))
            {
                if (bSerialize)
                {
                    return $"_buf.WriteFloat({fieldName});";
                }
                else
                {
                    return $"{declaration}{fieldName} = _buf.ReadFloat();";
                }
            }
            else if (rFieldType == typeof(ushort))
            {
                if (bSerialize)
                {
                    return $"_buf.WriteShort((short){fieldName});";
                }
                else
                {
                    return $"{declaration}{fieldName} = (ushort)_buf.ReadShort();";
                }
            }
            else if (rFieldType == typeof(short))
            {
                if (bSerialize)
                {
                    return $"_buf.WriteShort({fieldName});";
                }
                else
                {
                    return $"{declaration}{fieldName} = _buf.ReadShort();";
                }
            }
            else if (rFieldType.IsEnum)
            {
                Type underlyingType = Enum.GetUnderlyingType(rFieldType);
                if (bSerialize)
                {
                    if (underlyingType == typeof(byte))
                    {
                        return $"_buf.WriteByte((byte){fieldName});";
                    }
                    else
                    {
                        return $"_buf.WriteInt((int){fieldName});";
                    }
                }
                else
                {
                    if (underlyingType == typeof(byte))
                    {
                        return $"{declaration}{fieldName} = ({rFieldType.GetFullyQualifiedName()})_buf.ReadByte();";
                    }
                    else
                    {
                        return $"{declaration}{fieldName} = ({rFieldType.GetFullyQualifiedName()})_buf.ReadInt();";
                    }
                }
            }
            else if (rFieldType == typeof(List<string>) || rFieldType == typeof(IReadOnlyList<string>))
            {
                if (bSerialize)
                {
                    return $"SerializeByteBufUtil.SerializeListString(_buf, {fieldName});";
                }
                else
                {
                    return $"{declaration}{fieldName} = SerializeByteBufUtil.DeSerializeListString(_buf);";
                }
            }
            else if (rFieldType == typeof(List<int>) || rFieldType == typeof(IReadOnlyList<int>))
            {
                if (bSerialize)
                {
                    return $"SerializeByteBufUtil.SerializeListInt(_buf, {fieldName});";
                }
                else
                {
                    return $"{declaration}{fieldName} = SerializeByteBufUtil.DeSerializeListInt(_buf);";
                }
            }
            else if (rFieldType == typeof(List<long>) || rFieldType == typeof(IReadOnlyList<long>))
            {
                if (bSerialize)
                {
                    return $"SerializeByteBufUtil.SerializeListLong(_buf, {fieldName});";
                }
                else
                {
                    return $"{declaration}{fieldName} = SerializeByteBufUtil.DeSerializeListLong(_buf);";
                }
            }
            else if (rFieldType == typeof(List<ushort>) || rFieldType == typeof(IReadOnlyList<ushort>))
            {
                if (bSerialize)
                {
                    return $"SerializeByteBufUtil.SerializeListUshort(_buf, {fieldName});";
                }
                else
                {
                    return $"{declaration}{fieldName} = SerializeByteBufUtil.DeSerializeListUshort(_buf);";
                }
            }
            else if (rFieldType == typeof(List<short>) || rFieldType == typeof(IReadOnlyList<short>))
            {
                if (bSerialize)
                {
                    return $"SerializeByteBufUtil.SerializeListShort(_buf, {fieldName});";
                }
                else
                {
                    return $"{declaration}{fieldName} = SerializeByteBufUtil.DeSerializeListShort(_buf);";
                }
            }
            //底层不好改的class（存在s_toSerializeFixedType里的）和对应的list
            else if (IsList(rFieldType) && s_toSerializeFixedType.Contains(GetElementType(rFieldType)))
            {
                //List
                if (bSerialize)
                {
                    return $"{fieldName}.SerializeList(_buf);";
                }
                else
                {
                    return $"{declaration}{fieldName} = default; {fieldName} = {fieldName}.{(rFieldType.IsArray ? "DeserializeArray" : "DeserializeList")}(_buf);";
                }
            }
            else if (s_toSerializeFixedType.Contains(rFieldType))
            {
                //Object or struct
                if (bSerialize)
                {
                    return $"{fieldName}.Serialize(_buf);";
                }
                else
                {
                    return $"{declaration}{fieldName} = default; {fieldName} = {fieldName}.Deserialize(_buf);";
                }
            }
            //常规对象和对象List
            else if (IsList(rFieldType) && GetElementType(rFieldType).GetInterfaces().Contains(typeof(ISerializeByteBuf)))
            {
                //List
                if (bSerialize)
                {
                    return $"SerializeByteBufUtil.SerializeList(_buf, {fieldName});";
                }
                else
                {
                    return $"{declaration}{fieldName} = SerializeByteBufUtil.{(rFieldType.IsArray ? "DeSerializeArray" : "DeSerializeList")}<{GetElementType(rFieldType).GetFullyQualifiedName()}>(_buf);";
                }
            }
            else if (rFieldType.GetInterfaces().Contains(typeof(ISerializeByteBuf)))
            {
                //Object
                if (bSerialize)
                {
                    return $"SerializeByteBufUtil.SerializeObject(_buf, {fieldName});";
                }
                else
                {
                    return $"{declaration}{fieldName} = SerializeByteBufUtil.DeSerializeObject<{rFieldType.GetFullyQualifiedName()}>(_buf);";
                }
            }
            //自动序列化的抽象类
            else if (IsList(rFieldType) && s_SubClassEnumDict.ContainsKey(GetElementType(rFieldType)))
            {
                //List
                Type abBaseType = GetElementType(rFieldType);
                string enumFileName = s_SubClassEnumDict2[abBaseType];
                if (bSerialize)
                {
                    return $"int len{fieldIndex} = {fieldName}?.Count ?? 0; _buf.WriteInt(len{fieldIndex}); for (int i = 0; i < len{fieldIndex}; i++) {{ var ele = {fieldName}[i]; _buf.WriteInt({enumFileName}Map.GetEnumValue(ele)); (ele as ISerializeByteBuf)?.Serialize(_buf); }}";
                }
                else
                {
                    return $"int len{fieldIndex} = _buf.ReadInt(); {declaration}{fieldName} = new(len{fieldIndex}); for (int i = 0; i < len{fieldIndex}; i++) {{ var ele = {enumFileName}Map.CreateObj(_buf.ReadInt()); ele?.DeSerialize(_buf); {fieldName}.Add(ele as {abBaseType.GetFullyQualifiedName()}); }}";
                }
            }
            else if (s_SubClassEnumDict.ContainsKey(rFieldType))
            {
                //Object
                Type abBaseType = rFieldType;
                string enumFileName = s_SubClassEnumDict2[abBaseType];
                if (bSerialize)
                {
                    return $"_buf.WriteInt({enumFileName}Map.GetEnumValue({fieldName})); ({fieldName} as ISerializeByteBuf)?.Serialize(_buf);";
                }
                else
                {
                    return $"var obj{fieldIndex} = {enumFileName}Map.CreateObj(_buf.ReadInt()); obj{fieldIndex}?.DeSerialize(_buf); {declaration}{fieldName} = obj{fieldIndex} as {abBaseType.GetFullyQualifiedName()};";
                }
            }
            else if (IsDictionary(rFieldType))
            {
                var kvs = rFieldType.GetGenericArguments();
                Type keyType = kvs[0];
                Type valueType = kvs[1];
                if (bSerialize)
                {
                    return $"SerializeByteBufUtilExt.SerializeDict{keyType.Name}{valueType.Name}(_buf, {fieldName});";
                }
                else
                {
                    return $"{declaration}{fieldName} = SerializeByteBufUtilExt.DeserializeDict{keyType.Name}{valueType.Name}(_buf);";
                }
            }
            Debug.LogWarning($"不支持自动序列化字段类型{rFieldType}");
            return null;
        }

        private static bool IsDictionary(Type type)
        {
            return type.IsGenericType
                && (type.GetGenericTypeDefinition() == typeof(Dictionary<,>) || type.GetGenericTypeDefinition() == typeof(IReadOnlyDictionary<,>));
        }

        private static bool IsList(Type type)
        {
            bool isList = type.IsGenericType
                && (type.GetGenericTypeDefinition() == typeof(List<>) || type.GetGenericTypeDefinition() == typeof(IReadOnlyList<>));
            bool isArray = type.IsArray;
            return isList || isArray;
        }

        private static Type GetElementType(Type listType)
        {
            if (listType.IsGenericType)
            {
                return listType.GenericTypeArguments[0];
            }
            else if (listType.IsArray)
            {
                return listType.GetElementType();
            }
            return null;
        }

        private static void SaveCode(string path, string code)
        {
            if (path.IndexOf('\\') != -1)
            {
                path = path.Replace("\\", "/");
            }
            var dir = path.Substring(0, path.LastIndexOf('/'));
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            File.WriteAllText(path, code, UTF8);
        }
    }
}